package com.feifan.consumer.interceptor;

import com.alibaba.dubbo.config.annotation.Reference;
import com.feifan.api.annotation.UserLoginToken;
import com.feifan.api.model.UmsAdmin;
import com.feifan.api.service.ITokenService;
import com.feifan.api.service.IUserService;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.logging.Handler;

/**
 * @program: FinalProject
 * @author: Xiaofan
 * @createTime: 2021-08-04 20:23
 * @description: Functions of this class is 自定义的一个拦截器
 **/
public class AuthenticationInterceptor implements HandlerInterceptor {
    //dobbo做法
    @Reference(
            version = "1.0.0",
            interfaceName = "com.feifan.api.service.ITokenService",
            interfaceClass = ITokenService.class,
            timeout = 170000//防止一下子找不到zookeeper就连接中断
    )
    private ITokenService tokenService;
    //dobbo做法
    @Reference(
            version = "1.0.0",
            interfaceName = "com.feifan.api.service.IUserService",
            interfaceClass = IUserService.class,
            timeout = 170000
            //这个timeout时间一定要设置的长一点，不然当连接不上了就直接报错了！！！
    )
    private IUserService service;

    @Override//在核心业务之前来执行该方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //先从http头部取出token
        String token=request.getHeader("Authorization");//通过该特殊的键去找到token
        if(!(handler instanceof HandlerMethod)){
            //如果不是映射到方法级别的，则直接通过(即不是这种eg:“/flogin”直接映射到->方法faceLogin)
            return true;
        }
        else {
            //如果是映射到方法级别的，则取出该方法来
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();

            if (method.isAnnotationPresent(UserLoginToken.class)) {//指该方法必须通过token的验证
                UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);//取出该注解
                if (userLoginToken.required()) {//看该注解是否需要token的验证
                    //如果是的话，
                    if (token == null) {
                        //但是如果token为空的话，直接抛出异常
                        throw new RuntimeException("token不存在，请重新登录！");
                    }
                    //token存在，可以用来操作，获取其userId
                    token = token.split("@")[1];//取出真正的token
                    String userId = tokenService.getUserId(token);//通过token来取出userId
                    //然后通过userId去找到用户
                    UmsAdmin admin = service.findByUserId(userId);
                    if (admin == null) {
                        throw new RuntimeException("改用户不存在，请重新登录！");
                    }
                    //否则该用户存在
                    if (tokenService.checkSign(token, admin.getPassword())) {//进行token登录验证
                        return true;
                    } else {
                        throw new RuntimeException("token验证失败，请重新登录！");
                    }
                }
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("AfterCompletion");
    }
}